package com.neusoft.hifly.dynamicds.multi;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Map;
import java.util.WeakHashMap;

import javax.sql.DataSource;

import org.springframework.jdbc.datasource.AbstractDataSource;

import com.neusoft.hifly.dynamicds.druid.DruidDBConfig;

/**
 * Title: 分布式动态数据源路由
 * <p>
 * Description: 动态数据源实现类
 * <p>
 * 客户端使用路由时，在Spring Boot 启动类上添加@EnableDynamicDS注解
 * <p>
 * Copyright: 2019
 * <p>
 * Company: 东软汉枫
 * 
 * @author lh_neu
 * @version 1.0.0
 */
public class MultiDynamicDatasource extends AbstractDataSource {

	// 缓存数据源
	private Map<String, DataSource> dataSourceMap = new WeakHashMap<String, DataSource>(0);

	private DruidDBConfig druidDBConfig;

	public void setDsProperties(DruidDBConfig druidDBConfig) {
		this.druidDBConfig = druidDBConfig;
	}

	/**
	 * 当一个请求需要访问数据源时，它会根据OrganCodeHolder.getOrganCode()得到当前请求线程的organCode，尝试从缓存中按照organCode查找是否存在对应的数据源，如果不存在，则会根据配置信息构造一个HikariDataSource数据源实例塞入缓存中并得到Connection，然后把得到的Connection对象返回
	 */
	@Override
	public Connection getConnection() throws SQLException {
		MultiOrganDataSource currentOrganCode = MultiDataSourceContextHolder.getOrganDataSource();
		if (currentOrganCode == null) {
			// 默认数据源
			DataSource def = dataSourceMap.get("DEF");
			if (def == null) {
				def = druidDBConfig.defaultDataSource();
				dataSourceMap.put("DEF", def);
			}
			return def.getConnection();
		}

		DataSource ds = dataSourceMap.get(currentOrganCode.getOrganCode());
		//double check
		if (ds == null) {
			ds = currentOrganCode.getDataSource();
			dataSourceMap.put(currentOrganCode.getOrganCode(), ds);
		}
		return ds.getConnection();
	}

	@Override
	public Connection getConnection(String username, String password) throws SQLException {
		throw new SQLFeatureNotSupportedException();
	}
}
